<?php

    #-------------------------------------------------------------#
	# This file is part of the Tekuna MVC Microframework for PHP. #
	# (c) 2009 Niels Jäckel <niels.jaeckel@tekuna.org>            #
	# Please visit http://tekuna.org/ for more information.       #
	#                                                             #
	# This software is licensed under the MIT License. Please     #
	# view the LICENSE file for the full text of this license.    #
    #-------------------------------------------------------------#


	Tekuna :: load('org.tekuna.core.application.TekunaApplication');
	Tekuna :: load('org.tekuna.test.core.helper.RequestMock');
	Tekuna :: load('org.tekuna.test.core.helper.TekunaApplicationMock');


	class ApplicationTest extends AbstractTekunaTestCase {

		public function setUp() {

			parent :: setUp();

			// init SERVER array
			$_SERVER = array('REMOTE_ADDR' => '127.0.0.1',
			                 'REMOTE_PORT' => 3456,
			                 'HTTP_USER_AGENT' => 'TestClient/1.0',
			                 'HTTP_ACCEPT' => '*',
			                 'SERVER_PROTOCOL' => 'HTTP/1.1',
			                 'REQUEST_METHOD' => 'GET',
			                 'PHP_AUTH_USER' => 'authUser',
			                 'PHP_AUTH_PW' => 'authPassword',
			                 'HTTPS' => 'on');
		}


		protected function getApplicationInstance() {

			$sConfigFileName = 'testConfigs/validApplicationConfig.xml';
			$objApplication = new TekunaApplication($sConfigFileName);

			return $objApplication;
		}


		public function testConstants() {

			$this -> assertIdentical(TekunaApplication :: ACTION_FIELD, 'action');
			$this -> assertIdentical(TekunaApplication :: BASEDIR_LAYOUTS, 'layouts/');
			$this -> assertIdentical(TekunaApplication :: BASEDIR_FRAGMENTS, 'fragments/');
			$this -> assertIdentical(TekunaApplication :: BASEDIR_COMPONENTS, 'components/');
			$this -> assertIdentical(TekunaApplication :: BASEDIR_LANGFILES, 'lang/');
		}


		public function testGetters() {

			// get new application instance
			$objApplication = $this -> getApplicationInstance();

			// test config file storage
			$sConfigFileName = 'testConfigs/validApplicationConfig.xml';
			$this -> assertIdentical($objApplication -> getApplicationConfigFile(), APPLICATION_ROOT . $sConfigFileName);

			// context
			$objContext = $objApplication -> getApplicationContext();
			$this -> assertIdentical(get_class($objContext), 'TekunaApplicationContext');
			$this -> assertIdentical(get_class($objContext -> getRequest()), 'Request');
			$this -> assertIdentical(get_class($objContext -> getResponse()), 'Response');
			$this -> assertIdentical(get_class($objContext -> getClientInformation()), 'ClientInformation');
			$this -> assertIdentical(get_class($objApplication -> getLanguageChooser()), 'DefaultLanguageChooser');
			$this -> assertIdentical(get_class($objApplication -> getModuleProcessor()), 'DefaultModuleProcessor');
			$this -> assertIdentical(get_class($objApplication -> getLayoutComposer()), 'DefaultLayoutComposer');

			// language chooser
			$this -> assertIdentical(get_class($objApplication -> getLanguageChooser()), 'DefaultLanguageChooser');

			// module processor
			$this -> assertIdentical(get_class($objApplication -> getModuleProcessor()), 'DefaultModuleProcessor');

			// layout composer
			$this -> assertIdentical(get_class($objApplication -> getLayoutComposer()), 'DefaultLayoutComposer');
		}


		public function testProtocolIdentity() {

			// get new application instance
			$objApplication = $this -> getApplicationInstance();

			// test protocol equality
			$objContext = $objApplication -> getApplicationContext();
			$this -> assertIdentical($objContext -> getRequest() -> getRequestProtocol(), $objContext -> getResponse() -> getResponseProtocol());
		}


		public function testTekunaAction() {

			// test valid action
			$_GET['action'] = '/myController/myAction';
			$objApplication = $this -> getApplicationInstance();
			$this -> assertIdentical($objApplication -> getTekunaAction(), '/myController/myAction');

			// test action for filtering
			$_GET['action'] = 'myController/{myAction}';
			$objApplication = $this -> getApplicationInstance();
			$this -> assertIdentical($objApplication -> getTekunaAction(), '/myController/myAction');
		}


		public function testApplicationClassLoad() {

			// class file must not exist
			$this -> assertFalse(class_exists('ApplicationClassLoadTestClass', false));

			// loading of the class file with application class loader
			TekunaApplication :: load('components.controller.helper.ApplicationClassLoadTestClass');

			// now the class should exist
			$this -> assertTrue(class_exists('ApplicationClassLoadTestClass', false));

			// test exception for non existent classes
			try {

				TekunaApplication :: load('NonExistingClass');
				$this -> fail();
			}
			catch (TekunaClassLoadException $e) {

				$this -> pass();
			}
		}


		public function testControllerInstanceBuilder() {

			$objContext = new TekunaApplicationContext();
			$objContext -> setURLInformation(new URLInformation());

			// test valid controller instance
			$objController = TekunaApplication :: getControllerInstance('TestController', $objContext);
			$this -> assertIdentical(get_class($objController), 'TestController');

			// test controller not found
			try {

				$objController = TekunaApplication :: getControllerInstance('NonExistentController', $objContext);#
				$this -> fail();
			}
			catch (TekunaApplicationException $e) {

				$this -> pass();
			}

			// test controller class type
			try {

				$objController = TekunaApplication :: getControllerInstance('helper.ApplicationClassLoadTestClass', $objContext);#
				$this -> fail();
			}
			catch (TekunaApplicationException $e) {

				$this -> pass();
			}
		}


		public function testHandleRequest() {

			// test outputs of two requests
			$objApplication = new TekunaApplicationMock('testConfigs/completeRunApplicationConfig.xml');
			$objApplication -> handleRequest('/test/foo.html');
			$this -> assertIdentical($objApplication -> getApplicationContext() -> getResponse() -> getContent(), "Foo result\ntestOutput\nFoo result");

			$objApplication = new TekunaApplicationMock('testConfigs/completeRunApplicationConfig.xml');
			$objApplication -> handleRequest('/test/bar.html');
			$this -> assertIdentical($objApplication -> getApplicationContext() -> getResponse() -> getContent(), "Foo result\ntestOutput\nBar result");

			// test runtime URL and language values
			$objApplication = new TekunaApplicationMock('testConfigs/completeRunApplicationConfig.xml');
			$objApplication -> handleRequest('/runtimeTest/test.html');
			$this -> assertIdentical($objApplication -> getApplicationContext() -> getResponse() -> getContent(), "/runtimeTest/test.html\n/runtimeTest/\ntest.html\nen");

			// test context value replacements (including implicit language and base path replacement)
			$objApplication = new TekunaApplicationMock('testConfigs/completeRunApplicationConfig.xml');
			$objApplication -> handleRequest('/runtimeTest/context.html');
			$this -> assertIdentical($objApplication -> getApplicationContext() -> getResponse() -> getContent(), "en\n../\nfoo1\nbar/baz");
		}
	}



